package cc.linker.steplink.crm.service.impl;

import cc.linker.steplink.crm.commons.constant.TlPayConstant;
import cc.linker.steplink.crm.commons.constant.WcPayConstant;
import cc.linker.steplink.crm.commons.domain.WxUser;
import cc.linker.steplink.crm.commons.enums.IntegralEnums;
import cc.linker.steplink.crm.commons.http.HttpService;
import cc.linker.steplink.crm.commons.model.WcPayProperties;
import cc.linker.steplink.crm.commons.yzj.YzjRequest;
import cc.linker.steplink.crm.dao.LevelDao;
import cc.linker.steplink.crm.dao.PersonalCenterDao;
import cc.linker.steplink.crm.dao.ScoreActDao;
import cc.linker.steplink.crm.dao.ScoreLogDao;
import cc.linker.steplink.crm.domain.BindCustomerInfoPo;
import cc.linker.steplink.crm.domain.ChangeLoginPo;
import cc.linker.steplink.crm.merchanth5.service.CustomerIntegralService;
import cc.linker.steplink.crm.merchanth5.service.MallBoomService;
import cc.linker.steplink.crm.merchanth5.service.MallService;
import cc.linker.steplink.crm.merchanth5.service.VipCustomerLogService;
import cc.linker.steplink.crm.merchanth5.service.redis.SystemConfigService;
import cc.linker.steplink.crm.merchanth5.util.MD5;
import cc.linker.steplink.crm.response.GlobalException;
import cc.linker.steplink.crm.response.ResponseException;
import cc.linker.steplink.crm.service.CustomerService;
import cc.linker.steplink.crm.service.IPersonalCenterService;
import cc.linker.steplink.crm.service.ISyncService;
import com.alibaba.fastjson.JSON;
import com.alibaba.fastjson.serializer.SerializerFeature;
import lombok.extern.slf4j.Slf4j;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.beans.factory.annotation.Value;
import org.springframework.data.redis.core.StringRedisTemplate;
import org.springframework.scheduling.annotation.EnableAsync;
import org.springframework.stereotype.Service;
import org.springframework.util.StringUtils;

import java.util.ArrayList;
import java.util.HashMap;
import java.util.List;
import java.util.Map;
import java.util.concurrent.TimeUnit;

@EnableAsync
@Slf4j
@Service
public class PersonalCenterServiceImpl implements IPersonalCenterService {

    @Autowired
    private PersonalCenterDao personalCenterDao;

    @Autowired
    private ScoreActDao scoreActDao;

    @Autowired
    private LevelDao levelDao;

    @Autowired
    private ScoreLogDao scoreLogDao;

    @Autowired
    private MallBoomService mallBoomService;

    @Autowired
    private StringRedisTemplate stringRedisTemplate;

    @Autowired
    private MallService mallService;

    @Autowired
    private HttpService httpService;

    @Autowired
    private WcPayProperties wcPayProperties;

    @Autowired
    private SystemConfigService systemConfigService;

    @Autowired
    private CustomerIntegralService customerIntegralService;

    @Autowired
    private VipCustomerLogService vipCustomerLogService;

    @Autowired
    private CustomerService customerService;
    @Autowired
    private ISyncService syncService;

    @Autowired
    private YzjRequest yzjRequest;

    private final static String H5_SH5 = "SH5:";
    private final static String H5_SH5CHECK = "SH5CHECK:";

    @Value("${yzj.orgId}")
    public String yzjOrgId;

    @Override
    public Map<String, Object> get(String customerId,String bindPhone, Integer payMode) throws Exception {
        if (StringUtils.isEmpty(customerId)) {
            throw new GlobalException(new ResponseException(400, "客户customerId不能为空"));
        }
        Map<String, Object> result = new HashMap<>();
        Map<String, Object> record = personalCenterDao.get(customerId, payMode);
        record.put("customerPhone", bindPhone);
        Map<String, Object> orderNums = personalCenterDao.getOrderNums(customerId, payMode);
        result.putAll(record);
        result.putAll(orderNums);
        return result;
    }

    @Override
    public Map<String, Object> getCustomerByOpenIdAndToken(String openId, String token) {
        Map<String, Object> record = personalCenterDao.getCustomerByOpenIdAndToken(openId, token);
        return record;
    }

    @Override
    public Map<String, Object> getCustomerByGlobalOpenidAndToken(String globalOpenId, String token) {
        Map<String, Object> record = personalCenterDao.getCustomerByGlobalOpenid(globalOpenId, token);
        return record;
    }

    @Override
    public Integer getPayMode(String orgId) {
        return systemConfigService.getOrgPayModeByOrgId(orgId);
    }

    @Override
    public Map<String, Object> getBindInfo(String customerId) {
        return personalCenterDao.getBindInfo(customerId);
    }

    @Override
    public void bindPhone(Map<String, Object> params,String key,WxUser wxUser) {

        //获取当前用户绑定的手机号码是否有对应的用户信息
        Map<String, Object> otherCustomerInfo = personalCenterDao.getCustomerByPhone(params);

        // 如果没有找到绑过该手机号的用户信息
        if (null == otherCustomerInfo) {
            //如果该用户没有填写customerPhone，在绑定手机号的时候给他写入
            String customerPhone = personalCenterDao.ifExistBindPhone(params);
            if (StringUtils.isEmpty(customerPhone)) {
                params.put("customerPhone", params.get("phone"));
            }
            // 更新当前绑定手机号
            personalCenterDao.bindPhone(params);
            // 更新懂小姐手机号
            personalCenterDao.updateMissPhone(params);
            if (!StringUtils.isEmpty(params.get("orgId")) && yzjOrgId.equals(params.get("orgId").toString())) {
                //如果是雅智捷的，需要判断雅智捷用没有用户，没有需要同步
                customerService.ansyYzjCustomer(params);
            }
            wxUser.setBindPhone(params.get("phone").toString());
            stringRedisTemplate.opsForValue().set("login:" + key, com.alibaba.fastjson.JSON.toJSONString(wxUser), 15, TimeUnit.MINUTES);
        } else {
            /* 如果有人绑定过该手机号码
             *  1、判断绑过手机号的用户的来源是否跟当前的渠道不一致，如果不一致则加上当前渠道，并修改最后编辑时间
             *  2、切换账号登录（登录为对方的账号信息），需要在关联表修改当前的openid token对应的cid
             *  3、更新当前redis及session的登录信息
             */

            // region 第一步修改将要绑定用户的多渠道信息

            // 被绑用户多渠道
            Map<String, Object> otherCustomerSourceInfo = personalCenterDao.getCustomerSourceByCustomerId((String) otherCustomerInfo.get("customerId"));
            // 被绑用户来源
            Integer otherCustomerSourceI = (Integer) otherCustomerInfo.get("customerSourceChannel");
            String otherCustomerSource = String.valueOf(otherCustomerSourceI);

            // 绑定用户来源
            String customerSource = params.get("customerSourceChannel").toString();
            // 绑定用户多渠道
            Map<String, Object> customerSourceInfo = personalCenterDao.getCustomerSourceByCustomerId((String) params.get("customerId"));

            String bindPhone = StringUtils.isEmpty(params.get("bindPhone")) ? "" : params.get("bindPhone").toString();

            //将要关联的渠道Map
            Map<String, Object> sources = new HashMap<>();
            sources.put("orgId", params.get("orgId"));
            String newSource = "";
            // 判断绑定的人渠道中是否包含 这个人的渠道
            if (!otherCustomerSource.contains(customerSource)) {
                //如果不存在
                sources.put("customerId", otherCustomerInfo.get("customerId"));
                if (StringUtils.isEmpty(otherCustomerSourceInfo)) {
                    newSource = otherCustomerSource + "," + customerSource;
                } else {
                    // 已经是多渠道 是否包含 customerSource
                    if (!(otherCustomerSourceInfo.get("customerSourceChannel").toString().contains(customerSource))) {
                        newSource = otherCustomerSourceInfo.get("customerSourceChannel").toString() + "," + customerSource;
                    }
                }
            }

            //判断如果需要更新多渠道信息，则更新该用户的渠道信息
            if (!StringUtils.isEmpty(newSource)) {
                sources.put("customerSource", newSource);
                personalCenterDao.insertCustomerSource(sources);
            }
            // endregion

            // region 第二步修改当前登录信息表中对应公众号OpenId对应的 本系统用户Cid信息
            Map<String, Object> loginCustomerInfo = new HashMap<>();
            //新的绑定的手机号码
            loginCustomerInfo.put("phone", params.get("phone"));
            //当前登录用户及（当前微信客户端登录的openid，微信公众号）
            loginCustomerInfo.put("openId", params.get("openId"));
            //当前登录用户的微信公众号
            loginCustomerInfo.put("token", params.get("token"));
            //将要切换的用户的我们系统中的CID
            loginCustomerInfo.put("customerId", otherCustomerInfo.get("customerId"));
            //该字段为预留的ID
            loginCustomerInfo.put("appOpenId", "");
            loginCustomerInfo.put("orgId", params.get("orgId"));
            personalCenterDao.addBusiPhone(loginCustomerInfo);

            Map<String, Object> yzjUserInfo = new HashMap<>();


            // endregion

            // region 第三步这里要开始更新session的数据
            String sessionGlobalOpenid = (String) params.get("openId");
            String sessionPayOpenid = (String) params.get("payOpenId");
            String sessionOrgId = (String) params.get("orgId");
            String sessionToken = (String) params.get("token");
            String sessionOpenid = (String) params.get("openId");
            Integer isVip = 0;
            if (!StringUtils.isEmpty(params.get("isVip"))) {
                isVip = Integer.valueOf(params.get("isVip").toString());
            }
            String sessionCustomerId = (String) otherCustomerInfo.get("customerId");
            Map<String, Object> customerInfo = mallBoomService.getCustomerInfoByCustomerId(sessionCustomerId);
            String sessionNickName = (String) customerInfo.get("customerName");
            Integer payMode = mallService.getPayModeByOrgId(sessionOrgId);
            wxUser = new WxUser(sessionOpenid,
                    sessionPayOpenid,
                    sessionToken,
                    sessionNickName,
                    sessionOrgId,
                    sessionCustomerId,
                    sessionGlobalOpenid,
                    payMode,
                    isVip,
                    params.get("phone").toString(),
                    (customerInfo.containsKey("wxAvatar") && !StringUtils.isEmpty(customerInfo.containsKey("wxAvatar")) ? customerInfo.get("wxAvatar").toString() : ""), "");
            String h5User = JSON.toJSONString(wxUser, SerializerFeature.WriteMapNullValue);
            //更新缓存
            stringRedisTemplate.opsForValue().set("login:" + key, h5User, 15, TimeUnit.MINUTES);
            // endregion
//            this.personalCenterDao.changeLoginCustomer(params.get("customerId").toString(),(String) otherCustomerInfo.get("customerId"),params.get("phone").toString());

            // 记录登录记录表 v1.11.16
            Map<String, Object> loginParam = new HashMap<>();
            loginParam.put("loginPhone", params.get("phone"));
            loginParam.put("loginCustomerId", otherCustomerInfo.get("customerId"));
            loginParam.put("orgId", params.get("orgId"));
            loginParam.put("openId", params.get("openId"));
            loginParam.put("token", params.get("token"));
            personalCenterDao.addLoginLog(loginParam);
        }

        //region 切换完毕推送到队列告知所有的系统修改了绑定信息
        String newCustomerId = null == otherCustomerInfo ? params.get("customerId").toString() : otherCustomerInfo.get("customerId").toString();
        BindCustomerInfoPo newCustomerInfo = this.customerService.getOrgCustomerInfoByCustomerId(newCustomerId);
        newCustomerInfo.setCustomerPhone(params.get("phone").toString());
        ChangeLoginPo changeLoginPo = ChangeLoginPo.builder()
                .orgId(params.get("orgId").toString())
                .customerId(params.get("customerId").toString())
                .newCustomerInfo(newCustomerInfo).build();
//        rabbitTemplate.convertAndSend(QueueName.BIND_CUSTOMER, JSON.toJSONString(changeLoginPo, SerializerFeature.WriteMapNullValue));
        //endregion
    }

    @Override
    public Map<String, Object> getCustomerByCid(String customerId) {
        String customerInfoStr = stringRedisTemplate.opsForValue().get("home:customer_info_" + customerId);
        if (StringUtils.isEmpty(customerInfoStr)) {
            Map<String, Object> customerMap = personalCenterDao.getCustomerByCid(customerId);
            String customerMapString = JSON.toJSONStringWithDateFormat(customerMap, "yyyy-MM-dd", SerializerFeature.WriteDateUseDateFormat);
            stringRedisTemplate.opsForValue().set("home:customer_info_" + customerId, customerMapString,3,TimeUnit.MINUTES);
            return customerMap;
        } else {
            return (Map) JSON.parse(customerInfoStr);
        }
    }

    @Override
    public void openAccount(Map<String, Object> map) {
        new Thread(() -> {
            try {
                httpService.doPost(wcPayProperties.getAcsurl() + TlPayConstant.USER_CREATE_MEMBER, JSON.toJSONString(map), WcPayConstant.JSON);
            } catch (Exception e) {
                LOGGER.error("开户调用异常");
            }
        }).start();
    }

    @Override
    public List<Map<String, Object>> getScoreRule(String orgId) {
        Map map = new HashMap();
        map.put("orgId", orgId);
        List<Map<String, Object>> record = scoreActDao.listScoreAct(map);
        return record;
    }

    @Override
    public List<Map<String,Object>> getGrowTaskList(String type,String orgId) {
        List<Map<String, Object>> dataList = scoreActDao.getGrowTaskList(type,orgId);
        if (dataList != null && dataList.size() > 0) {
            for (Map<String, Object> dataMap : dataList) {
                if(!StringUtils.isEmpty(dataMap.get("activeType")) ){
                    String activeTip = "";
                    switch (dataMap.get("activeType").toString()){
                        case "custom":
                            activeTip = "自定义";
                            break;
                        case "share":
                            activeTip = "转发分享";
                            break;
                        case "comment":
                            activeTip = "文章评论";
                            break;
                        case "givestar":
                            activeTip = "文章点赞";
                            break;
                        case "buy":
                            activeTip ="购买商品";
                            break;
                        case "order":
                            activeTip ="完成下单";
                            break;
                        case "open":
                            activeTip ="分享传播";
                            break;
                        case "subscribe":
                            activeTip ="分享关注公众号";
                            break;
                        case "register":
                            activeTip ="邀请注册";
                            break;
                        case "deal":
                            activeTip ="分享成交";
                            break;
                        default:
                            break;
                    }
                    dataMap.put("activeTip", activeTip);
                }
                if (dataMap.get("scoreactType").toString().equals("custom")) {
                    List<Map<String, Object>> goodsRules = (List<Map<String, Object>>) JSON.parse(dataMap.get("rule").toString());
                    List<String> goodsIds = new ArrayList<>();
                    for (Map<String, Object> goodsRule : goodsRules) {
                        goodsIds.add(goodsRule.get("goodsId").toString());
                    }
                    List<Map<String, Object>> goodsList = this.mallBoomService.getGoodsInfoByGoodsIds(goodsIds);
                    for (Map<String, Object> goodsRule : goodsRules) {
                        for (Map<String, Object> goodsMap : goodsList) {
                            if(goodsRule.get("goodsId").toString().equals(goodsMap.get("goodsId").toString())){
                                goodsRule.put("goodsName",goodsMap.get("goodsName"));
                                goodsRule.put("goodsCover",goodsMap.get("goodsCover"));
                            }
                        }
                    }
                    dataMap.put("rules",goodsRules);
                } else {
                    dataMap.put("rules", (Map<String, Object>) JSON.parse(dataMap.get("rule").toString()));
                }
            }
        }
        return dataList;
    }

    @Override
    public List<Map<String, Object>> listScore(Map<String, String> map) {
        List<Map<String, Object>> record = scoreLogDao.listScore(map);
        return record;
    }

    @Override
    public void updateSubscribeByCustomerId(String subscribe, String customerId) {
        scoreLogDao.updateSubscribeByCustomerId(subscribe,customerId);
    }

    @Override
    public boolean isAppVip(String customerId){
        return personalCenterDao.isAppVip(customerId) > 0;
    }

    @Override
    public List<Map<String, Object>> levelRight(String levelId){
        return personalCenterDao.levelRight(levelId);
    }

    @Override
    public Map<String, Object> getLevelRightDetail(int rightId){
        return personalCenterDao.getLevelRightDetail(rightId);
    }

    @Override
    public Map<String, Object> getRule(Map<String,Object> param){
        Map<String, Object> rule = personalCenterDao.getRule(param);
        if(null == rule){
            Map<String, Object> rule2 = new HashMap<>();
            rule2.put("rule","");
            return rule2;
        }
        return rule;
    }

    @Override
    public Map<String, Object> getScoreLog(Map<String,Object> param){
        String customerId = param.get("customerId").toString();
        String orgId = param.get("orgId").toString();
        String integralFieldName = IntegralEnums.customerGrowthScore.toString();
        Integer pageIndex = Integer.valueOf(param.get("pageIndex").toString());
        Integer pageSize = Integer.valueOf(param.get("pageSize").toString());
        int scoreType = (int)param.get("scoreType");
        String sourceFieldName = null;
        switch (scoreType){
            case 0 :
                sourceFieldName = IntegralEnums.other.toString();
                break;
            case 1 :
                sourceFieldName = IntegralEnums.contentSystem.toString();
                break;
            case 2 :
                sourceFieldName = IntegralEnums.mallSystem.toString();
                break;
            default:
                break;
        }
        return this.customerIntegralService.getIntegralCustomerLogs(customerId,orgId,integralFieldName,pageIndex,sourceFieldName,pageSize);
//        return personalCenterDao.getScoreLog(param);
    }

    /**
     * 修改用户信息
     *
     * @param : customerId 会员id
     * @param : customerName 会员姓名
     * @param : wxGender 性别
     * @param : customerArea 地区
     * @param : customerBirth 生日
     * @param : type 修改类型 1.会员姓名 2.性别 3.地区 4.生日
     * @param params
     */
    @Override
    public void updateUserInfo(Map<String, Object> params, Integer type,String orgId,String globalopenId) {
        String customerId = params.get("customerId").toString();
        //获取count微信与小程序
        Integer count = personalCenterDao.getUserCount(customerId);
        if(count==0){
            personalCenterDao.insertUserWx(customerId);
        }
        if(type==1){
            //修改会员姓名
            personalCenterDao.updateCustomerName(params);
            String key = MD5.encode(orgId + globalopenId);
            String h5User = stringRedisTemplate.opsForValue().get("login:" + key);
            if(!StringUtils.isEmpty(h5User)){
                WxUser wxUser = JSON.parseObject(h5User, WxUser.class);
                wxUser.setNickname(params.get("customerName").toString());
                h5User = JSON.toJSONString(wxUser);
                stringRedisTemplate.opsForValue().set("login:" + key, h5User, 15, TimeUnit.MINUTES);
            }
        }else if(type==2){
            //修改会员性别
            personalCenterDao.updateWxGender(params);
        }else if(type==3){
            //修改会员地区
            String customerArea = "";
            if(!StringUtils.isEmpty(params.get("customerArea"))){
                customerArea = params.get("customerArea").toString();
            }
//            customerArea = customerArea.replaceAll("省","");
//            customerArea = customerArea.replaceAll("市","");
//            customerArea = customerArea.replaceAll("区","");
            personalCenterDao.updateCustomerArea(customerArea,customerId);
        }else if(type==4){
            //修改会员生日
            personalCenterDao.updateCustomerBirth(params);
        }
        stringRedisTemplate.delete("home:customer_info_" + customerId);
    }

}
